<template>
  <div class="progress-circle-wrap">
    <svg :width="size" :height="size" :viewBox="'0 0 ' + size + ' ' + size">
      <defs>
        <linearGradient :id="'g'+label" x1="0%" y1="0%" x2="100%" y2="0%">
          <stop offset="0%" :stop-color="colorFrom"/>
          <stop offset="100%" :stop-color="colorTo"/>
        </linearGradient>
        <filter id="glow">
          <feGaussianBlur stdDeviation="3" result="coloredBlur"/>
          <feMerge>
            <feMergeNode in="coloredBlur"/>
            <feMergeNode in="SourceGraphic"/>
          </feMerge>
        </filter>
      </defs>
      <circle :cx="size/2" :cy="size/2" :r="(size-stroke)/2" stroke="#0a2a4d" :stroke-width="stroke" fill="none"/>
      <circle
        :cx="size/2" :cy="size/2" :r="(size-stroke)/2"
        :stroke="'url(#g'+label+')'"
        :stroke-width="stroke"
        fill="none"
        stroke-linecap="round"
        :stroke-dasharray="Math.PI*(size-stroke)"
        :stroke-dashoffset="Math.PI*(size-stroke)*(1-percent/100)"
        filter="url(#glow)"
      />
    </svg>
    <div class="progress-circle-value">{{ displayValue }}<span class="progress-circle-unit">%</span></div>
    <div class="progress-circle-label">{{ label }}</div>
  </div>
</template>

<script setup>
import { ref, watch, onMounted } from 'vue';
const props = defineProps({
  value: { type: Number, required: true },
  label: { type: String, required: true },
  size: { type: Number, default: 80 },
  stroke: { type: Number, default: 10 },
  colorFrom: { type: String, default: '#00f0ff' },
  colorTo: { type: String, default: '#00ffb0' }
});
const percent = ref(0);
const displayValue = ref(0);
function animateTo(target) {
  let start = percent.value;
  let startTime = null;
  function animate(ts) {
    if (!startTime) startTime = ts;
    const progress = Math.min((ts - startTime) / 900, 1);
    percent.value = start + (target - start) * progress;
    displayValue.value = Math.round(percent.value);
    if (progress < 1) requestAnimationFrame(animate);
    else {
      percent.value = target;
      displayValue.value = Math.round(target);
    }
  }
  requestAnimationFrame(animate);
}
watch(() => props.value, (nv) => animateTo(nv));
onMounted(() => animateTo(props.value));
</script>

<style scoped>
.progress-circle-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  min-width: 90px;
  max-width: 120px;
  flex: 1 1 0;
  box-sizing: border-box;
}
.progress-circle-value {
  color: #00f0ff;
  font-size: 24px;
  font-weight: bold;
  text-shadow: 0 0 16px #00f0ff, 0 0 4px #fff;
  margin-top: -54px;
  margin-bottom: 8px;
  letter-spacing: 1px;
  position: relative;
  z-index: 2;
  animation: numberFloat 1.8s ease-in-out;
}
.progress-circle-unit {
  font-size: 14px;
  color: #7ee9ff;
  margin-left: 2px;
}
.progress-circle-label {
  color: #7ee9ff;
  font-size: 15px;
  margin-top: 0;
  letter-spacing: 1px;
  text-align: center;
  text-shadow: 0 0 8px #00f0ff99;
  white-space: nowrap;
}
@keyframes numberFloat {
  0% { color: #fff; text-shadow: none; }
  50% { color: #00f0ff; text-shadow: 0 0 16px #00f0ff; }
  100% { color: #00f0ff; text-shadow: 0 0 8px #00f0ff99; }
}
@media (max-width: 600px) {
  .progress-circle-wrap {
    min-width: 60px;
    max-width: 80px;
  }
}
</style> 